function Outp = mysourcedb(This,Range,varargin)
% mysourcedb  [Not a public function] Create model-specific source database.
%
% Backend IRIS function.
% No help provided.

% -IRIS Toolbox.
% -Copyright (c) 2007-2015 IRIS Solutions Team.

if ischar(Range)
    Range = textinp2dat(Range);
end

nCol = [];
if ~isempty(varargin) && isnumericscalar(varargin{1})
    nCol = varargin{1};
    varargin(1) = [];
end

opt = passvalopt('model.mysourcedb',varargin{:});

nDraw = opt.ndraw;
if isempty(nCol)
    nCol = opt.ncol;
end

%--------------------------------------------------------------------------

nAlt = size(This.Assign,3);

if (nCol>1 && nAlt>1) ...
        || (nDraw>1 && nAlt>1)
    utils.error('model:mysourcedb', ...
        ['The options `''nCol=''` or `''nDraw=''` can be used only with ', ...
        'single parameterisation models.']);
end

nf = sum(imag(This.solutionid{2})>2);
maxLag = -(min(imag(This.solutionid{2}(nf+1:end))) - 1);
xRange = Range(1)-maxLag : Range(end);
nXPer = length(xRange);
label = mylabelorname(This);

ny = sum(This.nametype==1);
nx = sum(This.nametype==2);
ne = sum(This.nametype==3);
ng = sum(This.nametype==5);

if nCol>1 && nAlt>1
    utils.error('model:mysourcedb', ...
        ['Input argument NCol can be used only with ', ...
        'single-parameterisation models.']);
end

n = ny + nx + ne;
nLoop = max([nAlt,nCol,nDraw]);
Outp = struct();

% Deterministic time trend.
timeTnd = dat2ttrend(xRange,This);

if opt.deviation
    X = zeros(n,nXPer,nAlt);
    G = zeros(ng,nXPer,nAlt);
else
    X = zeros(n,nXPer,nAlt);
    inx = find(This.nametype==1 | This.nametype==2);
    isDelog = false;
    X(inx,:,:) = mytrendarray(This,Inf,isDelog,inx,timeTnd);
    G = mytrendarray(This,Inf,isDelog,find(This.nametype==5),timeTnd);
end

if opt.dtrends
    D = mydtrendsrequest(This,'range',xRange,G);
    X(1:ny,:,:) = X(1:ny,:,:) + D;
end

X(This.IxLog(1:n),:,:) = real(exp(X(This.IxLog(1:n),:,:)));

if nLoop>1 && nAlt==1
    X = repmat(X,1,1,nLoop);
    G = repmat(G,1,1,nLoop);
end

% Measurement variables, transition variables.
tmp = tseries();
for i = find(This.nametype<=2)
    Outp.(This.name{i}) = replace(tmp, ...
        permute(X(i,:,:),[2,3,1]), ...
        xRange(1),label{i});
end

% Do not include pre-sample in shock series.
for i = find(This.nametype==3)
    x = X(i,maxLag+1:end,:);
    Outp.(This.name{i}) = replace(tmp, ...
        permute(x,[2,3,1]), ...
        Range(1),label{i});
end

% Generate random residuals if requested.
if opt.randshocks && ~isequal(opt.randfunc,@zeros)
    Outp = shockdb(This,Outp,Range,nLoop,'randfunc=',opt.randfunc);
end

% Add parameters.
for i = find(This.nametype==4)
    Outp.(This.name{i}) = permute(This.Assign(1,i,:),[1,3,2]);
end

% Add exogenous variables.
offset = sum(This.nametype<5);
for i = find(This.nametype==5)
    Outp.(This.name{i}) = ...
        replace(tmp,permute(G(i-offset,:,:),[2,3,1]), ...
        xRange(1),label{i});    
end

% Add time trend.
Outp.ttrend = replace(tmp,timeTnd.',xRange(1),'Time trend');    

end

